﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using MarioArena.World;

namespace MarioArena.Multiplayer
{
    class UDPSender
    {
        private UdpClient mUdpClient;
        private IPEndPoint mEndPoint; // IP and port

        /// <summary>
        /// Used by the SERVER for checking if a received packet is actually newer than the previously received package.
        /// </summary>
        private int mSentPacketCounter;

        /// <summary>
        /// Constructs a new UDPSender.
        /// </summary>
        /// <param name="udpClient">UdpClient instance.</param>
        /// <param name="endPoint">An IPEndPoint containing the IP-address and port of the server.</param>
        public UDPSender(UdpClient udpClient, IPEndPoint endPoint)
        {
            this.mUdpClient = udpClient;
            this.mEndPoint = endPoint;
        }

        /// <summary>
        /// Starts sending data via UDP.
        /// </summary>
        public void StartSending()
        {
            try
            {
                SendContinueousDataStream();
            }
            catch (Exception)
            {
                Console.WriteLine("Could not start UDPSender. Disconnected.");
                UDPConnection.Instance.IsConnected = false;
            }
        }

        /// <summary>
        /// Sends a continueous stream of the latest player data, which sent to 
        /// all other connected clients by the receiving server.
        /// </summary>
        private void SendContinueousDataStream()
        {
            string data_to_send = "";
            try
            {
                while (UDPConnection.Instance.IsConnected)
                {
                    // Send: CameraX_CameraY_SpeedX_SpeedY_Direction_LeftPressed_RightPressed
                    string leftPressed = "0";
                    string rightPressed = "0";
                    string jumpPressed = "0";
                    if (Player.Instance.LeftKeyPressed) leftPressed = "1";
                    if (Player.Instance.RightKeyPressed) rightPressed = "1";
                    if (Player.Instance.JumpKeyPressed) jumpPressed = "1";

                    // Make sure the server doesn't use this client's screen size for calculations.
                    // We add it here because it has been subtracted earlier in the client.
                    int cameraX = Camera.X + (GameManager.GraphicsDevice.Viewport.Width / 2);
                    int cameraY = Camera.Y + (GameManager.GraphicsDevice.Viewport.Height / 2);

                    data_to_send =
                        Player.Instance.Id + "#" +
                        this.mSentPacketCounter + "#" +
                        cameraX + "_" +
                        cameraY + "_" +
                        Player.Instance.Character.SpeedX.ToString() + "_" + 
                        Player.Instance.Character.SpeedY.ToString() + "_" +
                        Player.Instance.Character.Direction.ToString() + "_" + 
                        leftPressed.ToString() + "_" +
                        rightPressed.ToString() + "_" + 
                        jumpPressed.ToString();

                    // String data to bytes
                    byte[] datagram = Encoding.ASCII.GetBytes(data_to_send);
                    int dataLength = datagram.Count();

                    mUdpClient.Send(datagram, dataLength, this.mEndPoint);
                    this.mSentPacketCounter++; // Increase the packet counter each time a packet is sent

                    Thread.Sleep(5); // Performance improvement
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("ERROR WHILE SENDING DATA STREAM: " + e);
            }
        }
    }
}
